#!/usr/bin/python3

from os import environ, system
from os.path import exists, isdir
from sys import argv
from threading import Thread

from pyautogui import write
from prettytable import PrettyTable
from orjson import dumps, loads, OPT_APPEND_NEWLINE, OPT_INDENT_2
from inquirer import prompt, Checkbox, Confirm, List


class TodayToDo():
    def __init__(self):
        super(TodayToDo, self).__init__()
        self.path = f"{environ['HOME']}/.config/today-cli"
        self.config = f'{self.path}/todo.json'
        self.release = self.__getVersion()
        self.data = self.__get()

    def version(self): print(self.release)

    def __getVersion(self):
        with open(f'{environ["HOME"]}/.config/today-cli/.version', 'r') as f:
            return f.read().split('\n')[0]

    def setup(self):
        cdir = f'mkdir -p "{self.path}" > /dev/null'
        None if isdir(self.path) else system(cdir)
        None if exists(self.config) else system(f'touch {self.config}')

    def __get(self):
        if exists(self.config):
            with open(self.config, 'rb') as f:
                return loads(f.read())
        else:
            with open(self.config, 'w') as f:
                f.write([])
            return self.__get()

    def __set(self, data):
        if isinstance(data, list):
            with open(self.config, 'wb') as f:
                f.write(dumps(data, option=OPT_INDENT_2 | OPT_APPEND_NEWLINE))

    def added(self, *task):
        if task:
            [self.data.append({"name": i, "mode": "doing"}) for i in task]
            self.__set(self.data)
            self.show()
        else:
            raise ValueError('Input you correct task!')

    def removed(self):
        names = [i['name'] for i in self.data]
        answers = self.__toggled('Changing toggle mode of tasks', names)

        indexes = [names.index(i) for i in answers] if answers else None
        if indexes is not None:
            condition = "this" if len(indexes) == 1 else "these"
            msg = f'Are you sure you want to delete {condition} entry?'
            confirm = [Confirm('continue', message=msg)]
            if prompt(confirm)['continue']:
                self.data = [v for i, v in enumerate(self.data) if i not in indexes]
                self.__set(self.data)

        self.show()

    def __editable(self, task):
        Thread(target=write, args=(task,)).start()
        modified_input = input()
        return modified_input

    def edited(self):
        names = [i['name'] for i in self.data]
        msg = "What are you interested in?"
        ind = names.index(prompt([List('edit', message=msg,
                                      choices=names)])['edit'])
        task = self.__editable(self.data[ind]['name'])
        if task:
            self.data[ind]['name'] = task
            self.__set(self.data)
            self.show()
        else:
            raise ValueError('<task> cannot be empty!')

    def drop(self):
        msg = f'Are you sure you want to delete all tasks?'
        confirm = [Confirm('continue', message=msg)]
        self.__set([]) if prompt(confirm)['continue'] else None

    def show(self):
        if self.data:
            mode, inc, dec = {"doing": '◼️', "ended": '✅' }, 0, 0
            table = PrettyTable(['check', 'index', 'name'])
            for i, v in enumerate(self.data):
                if v['mode'] in 'doing':
                    inc += 1
                else:
                    dec += 1
                table.add_row((mode[v['mode']], i, v['name']))
            print(table)
            print('All tasks:', len(self.data), '\t[ Active:', inc,
                                                '\tUnactive:', dec,']')
        else:
            print('+----------------+')
            print('| No task yet!!! |')
            print('+----------------+')

    def __toggled(self, msg, names, modes=None):
        questions = [Checkbox('toggle', message=msg, choices=names,
                              default=modes if modes is not None else [])]
        return prompt(questions)['toggle']

    def toggle(self):
        names = [i['name'] for i in self.data]
        modes = [i['name'] for i in self.data if i['mode'] == 'ended']
        answers = self.__toggled('Changing toggle mode of tasks', names, modes)
        indexes = [names.index(i) for i in answers] if answers else None

        for i in range(len(self.data)):
            self.data[i]['mode'] = 'ended' if indexes is not None and \
                                              i in indexes else 'doing'

        self.__set(self.data)
        self.show()

    def help(self):
        return ('Simple ToDo List.\n',
                '\t\t\tList commands:\n',
                '\tinit | create\t\t\tcreate config file\n',
                '\tadd | insert | append\t\tcreate one or several new tasks\n',
                '\tedit\t\t\t\tediting name task\n',
                '\ttoggle | change\t\t\ttoggle mode one or several tasks\n'
                '\trm | remove\t\t\tdelete one or several tasks\n',
                '\tdrop\t\t\t\tdelete all tasks\n',
                '\tlist | show\t\t\tshow all list task\n\n',
                '\t-v --version\t\t\tshow current version\n',
                '\t-h --help\t\t\tshow list commands\n\n', self.release)


if __name__ == "__main__":
    todo = TodayToDo()
    commands = ('add', 'insert', 'append', 'rm', 'remove', 'edit', 'toggle',
                'change', 'drop', 'list', 'show', 'init', 'create',
                '-v', '--version')
    if len(argv) == 1 or argv[1] in ('--help', '-h') or len(argv) > 3 and \
                                                argv[1] not in commands[:8]:
        print('[ERROR]: Too many arguments\n' if len(argv) > 3 else '',
              *todo.help())
    elif argv[1] in ('add', 'insert', 'append'):
        todo.added(*argv[2:])
    elif argv[1] in ('rm', 'remove'):
        todo.removed()
    elif argv[1] in 'edit':
        todo.edited()
    elif argv[1] in ('toggle', 'change'):
        todo.toggle()
    elif argv[1] in 'drop':
        todo.drop()
    elif argv[1] in ('list', 'show'):
        todo.show()
    elif argv[1] in ('init', 'create'):
        todo.setup()
    elif argv[1] in ('--version', '-v'):
        todo.version()
    else:
        print('[ERROR]: Command', argv[1], 'is not supported\n', *todo.help())
